package com.cicadasmall.system.wrapper;

import com.cicadasmall.common.enums.UserTypeEnum;
import com.cicadasmall.common.exception.ServiceException;
import com.cicadasmall.common.func.Fn;
import com.cicadasmall.common.utils.SpringContextUtils;
import com.cicadasmall.common.utils.WarpsUtils;
import com.cicadasmall.common.wrapper.EntityWrapper;
import com.cicadasmall.data.domain.*;
import com.cicadasmall.security.LoginUserDetails;
import com.cicadasmall.system.service.IDeptService;
import com.cicadasmall.system.service.IMenuService;
import com.cicadasmall.system.service.IPositionService;
import com.cicadasmall.system.service.IRoleService;
import com.cicadasmall.system.vo.UserVO;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class UserWrapper implements EntityWrapper<UserDO, UserVO> {

    private final static IDeptService deptService;
    private final static IRoleService roleService;
    private final static IMenuService menuService;
    private final static IPositionService positionService;

    static {
        deptService = SpringContextUtils.getBean(IDeptService.class);
        roleService = SpringContextUtils.getBean(IRoleService.class);
        menuService = SpringContextUtils.getBean(IMenuService.class);
        positionService = SpringContextUtils.getBean(IPositionService.class);
    }

    public static UserWrapper newBuilder() {
        return new UserWrapper();
    }

    public LoginUserDetails loginUserDetails(UserDO entity) {
        UserVO userVO = entityVO(entity);
        LoginUserDetails loginUserDetails = WarpsUtils.copyTo(userVO, LoginUserDetails.class);
        if (Fn.equal(UserTypeEnum.系统.getCode(), loginUserDetails.getUserType())) {
            loginUserDetails.setRoleIds(userVO.getRoles().stream().map(RoleDO::getRoleId).collect(Collectors.toSet()));
            loginUserDetails.setRoleKeys(userVO.getRoles().stream().map(RoleDO::getRoleKey).collect(Collectors.toSet()));
            loginUserDetails.setDataScopes(userVO.getRoles().stream().map(RoleDO::getDataScope).collect(Collectors.toSet()));
        }
        return loginUserDetails;
    }

    @Override
    public UserVO entityVO(UserDO entity) {
        UserVO userVo = WarpsUtils.copyTo(entity, UserVO.class);
        //系统用户返回部门角色职位等选中信息
        if (Fn.equal(UserTypeEnum.系统.getCode(), userVo.getUserType())) {

            //设置用户所属部门
            List<DeptDO> deptList = deptService.findByUserId(userVo.getUid());
            if (Fn.isNotEmpty(deptList)) {
                userVo.setDepartments(deptList.stream().collect(Collectors.toSet()));
                userVo.setDeptName(deptList.stream().sorted(Comparator.comparing(DeptDO::getDeptId).reversed()).collect(Collectors.toList()).stream().findFirst().orElseThrow(new ServiceException("未找到所属部门！")).getDeptName());
                userVo.setSelectedDeptIds(userVo.getDepartments().stream().map(DeptDO::getDeptId).toArray(Integer[]::new));
            } else {
                userVo.setSelectedDeptIds(new Integer[]{});
            }

            //设置所属角色
            List<RoleDO> roleList = roleService.findByUserId(userVo.getUid());
            if (Fn.isNotEmpty(roleList)) {
                userVo.setRoles(roleList.stream().collect(Collectors.toSet()));
                userVo.setRoleName(roleList.stream().findFirst().orElseThrow(new ServiceException("未找到所属角色")).getRoleName());
                userVo.setSelectedRoleIds(userVo.getRoles().stream().map(RoleDO::getRoleId).toArray(Integer[]::new));
                //设置用户权限
                List<MenuDO> menuList = menuService.findByRoleIds(roleList.stream().map(RoleDO::getRoleId).collect(Collectors.toSet()));
                if (Fn.isNotEmpty(menuList)) {
                    userVo.setPermissions(menuList.stream().parallel().map(MenuDO::getPermissionKey).collect(Collectors.toSet()));
                }
            } else {
                userVo.setSelectedRoleIds(new Integer[]{});
            }

            //设置所属职位
            List<PositionDO> positions = positionService.findByUserId(userVo.getUid());
            if (Fn.isNotEmpty(positions)) {
                userVo.setPositions(positions.stream().collect(Collectors.toSet()));
                userVo.setPostName(positions.stream().findFirst().orElseThrow(new ServiceException("未找到所属岗位")).getPostName());
                userVo.setSelectedPostIds(userVo.getPositions().stream().map(PositionDO::getId).toArray(Integer[]::new));
            } else {
                userVo.setSelectedPostIds(new Integer[]{});
            }
        }
        return userVo;
    }


    @Override
    public List<UserVO> treeVO(List<UserDO> list) {
        return null;
    }
}
